001    /* EVolve - an Extensible Software Visualization Framework
002     * Copyright (C) 2001-2002 Qin Wang
003     *
004     * This library is free software; you can redistribute it and/or
005     * modify it under the terms of the GNU Library General Public
006     * License as published by the Free Software Foundation; either
007     * version 2 of the License, or (at your option) any later version.
008     *
009     * This library is distributed in the hope that it will be useful,
010     * but WITHOUT ANY WARRANTY; without even the implied warranty of
011     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
012     * Library General Public License for more details.
013     *
014     * You should have received a copy of the GNU Library General Public
015     * License along with this library; if not, write to the
016     * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
017     * Boston, MA 02111-1307, USA.
018     */
019    
020    /*
021     * EVolve is distributed at http://www.sable.mcgill.ca/EVolve/
022     */
023    
024    package EVolve.visualization;
025    
026    import EVolve.exceptions.NoDataPlotException;
027    
028    import java.awt.*;
029    import java.awt.image.*;
030    import java.util.*;
031    
032    /**
033     * Automatic expanding image.
034     */
035    public class AutoImage implements Cloneable{
036        protected short[][] image; // the image
037        protected int w, h; // width and height of the content
038        protected int wMax, hMax; // width and height of the image
039        protected int imageWidth, imageHeight;
040    
041        protected HashMap object2Int,Int2Object;
042    
043        /**
044         * Creates an auto-image.
045         */
046        public AutoImage() {
047            w = 0;
048            h = 0;
049            wMax = 200;
050            hMax = 200;
051            image = new short[wMax][hMax];
052            for (int i = 0; i < wMax; i++) {
053                for (int j = 0; j < hMax; j++) {
054                    image[i][j] = 0;
055                }
056            }
057            object2Int = new HashMap();
058            Int2Object = new HashMap();
059            object2Int.put(null,new Integer(0));
060            Int2Object.put(new Integer(0),null);
061        }
062    
063        /**
064         * Sets the color of a pixel.
065         *
066         * @param   x position on X-axis
067         * @param   y position on Y-axis
068         * @param   color the color
069         */
070        public void setColor(int x, int y, Object color) {
071            if ((x >= wMax) || (y >= hMax)) {
072                while (x >= wMax) {
073                    wMax += 200;
074                }
075                while (y >= hMax) {
076                    hMax += 200;
077                }
078    
079                short[][] newImage = new short[wMax][hMax];
080                for (int i = 0; i < wMax; i++) {
081                    for (int j = 0; j < hMax; j++) {
082                        newImage[i][j] = 0;
083                    }
084                }
085                for (int i = 0; i < w; i++) {
086                    for (int j = 0; j < h; j++) {
087                        newImage[i][j] = image[i][j];
088                    }
089                }
090                image = newImage;
091            }
092    
093            if (object2Int.containsKey(color)) {
094                image[x][y] = ((Integer)object2Int.get(color)).shortValue();
095            } else {
096                short size = (short)object2Int.size();
097                object2Int.put(color,new Integer(size));
098                Int2Object.put(new Integer(size),color);
099                image[x][y] = size;
100            }
101    
102            if (x >= w) {
103                w = x + 1;
104            }
105            if (y >= h) {
106                h = y + 1;
107            }
108        }
109    
110        /**
111         * Gets the color of a pixel.
112         *
113         * @param   x position on X-axis
114         * @param   y position on Y-axis
115         * @return  the color
116         */
117        public Object getColor(int x, int y) {
118            if ((image!=null) && ((x < 0) || (y < 0) || (x >= image.length) || (y >= image[0].length))) {
119                return null;
120            } else {
121                int index = image[x][y];
122                return Int2Object.get(new Integer(index));
123            }
124        }
125    
126        public Color getSortedColor(ReferenceDimension xAxis, ReferenceDimension yAxis,int x,int y) {
127            int xMappedId,yMappedId;
128            xMappedId = (xAxis == null) ? x : xAxis.getOriginMappedId(x);
129            yMappedId = (yAxis == null) ? y : yAxis.getOriginMappedId(y);
130    
131            if ((xMappedId >= wMax) || (yMappedId >= hMax) || (xMappedId < 0) || (yMappedId < 0))
132                return null;
133            else {
134                int index = image[xMappedId][yMappedId];
135                if (index == 0)
136                    return null;
137                else
138                    return (Color)Int2Object.get(new Integer(index));
139            }
140        }
141    
142        /**
143         * Gets the buffered-image.
144         *
145         * @return  buffered-image
146         */
147        public BufferedImage getImage() throws NoDataPlotException {
148    
149            if (w*h == 0) throw new NoDataPlotException();
150    
151            BufferedImage returnVal = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
152            returnVal.getGraphics().setColor(Color.white);
153            returnVal.getGraphics().fillRect(0, 0, w, h);
154    
155            for (int i = 0; i < w; i++) {
156                for (int j = 0; j < h; j++) {
157                    if (image[i][j] != 0) {
158                        returnVal.setRGB(i, j, ((Color)Int2Object.get(new Integer(image[i][j]))).getRGB());
159                    }
160                }
161            }
162    
163            return returnVal;
164        }
165    
166        /**
167         * Sorts the image.
168         *
169         * @param   xAxis dimension that represents the X-axis, null if doesn't need to be sorted
170         * @param   yAxis dimension that represents the Y-axis, null if doesn't need to be sorted
171         * @return  sorted image
172         */
173        public AutoImage getSortedImage(ReferenceDimension xAxis, ReferenceDimension yAxis) {
174            AutoImage returnVal = new AutoImage();
175            for (int i = 0; i < w; i++) {
176                for (int j = 0; j < h; j++) {
177                    int x, y;
178                    if (xAxis == null) {
179                        x = i;
180                    } else {
181                        x = xAxis.getSortedIndex(i);
182                    }
183                    if (yAxis == null) {
184                        y = j;
185                    } else {
186                        y = yAxis.getSortedIndex(j);
187                    }
188                    if ((x != -1) && (y != -1)) {
189                        returnVal.setColor(x, y, Int2Object.get(new Integer(image[i][j])));
190                    }
191                }
192            }
193            return returnVal;
194        }
195    
196        public int getDimension(int dim) {
197            if (dim == -1) return image.length;
198    
199            return image[dim].length;
200        }
201    
202        public int getW() {
203            return w;
204        }
205    
206        public int getH() {
207            return h;
208        }
209    
210        public void setImageWidth(int width, int height) {
211            imageWidth = w;
212            imageHeight = h;
213        }
214    
215        public short[][] getImageDataArray() {
216            return image;
217        }
218    
219        public Object clone() {
220            AutoImage o = null;
221            try {
222                o = (AutoImage)super.clone();
223            } catch (CloneNotSupportedException e) {
224                e.printStackTrace();
225                return o;
226            }
227    
228            o.Int2Object = new HashMap();
229            o.object2Int = new HashMap();
230            o.object2Int.put(null,new Integer(0));
231            o.Int2Object.put(new Integer(0),null);
232            o.image = new short[image.length][];
233            for (int i=0; i<image.length; i++) {
234                o.image[i] = new short[image[i].length];
235                for (int j=0; j<image[i].length; j++) {
236                    o.image[i][j] = image[i][j];
237                }
238            }
239            Iterator it = object2Int.keySet().iterator();
240            while (it.hasNext()) {
241                Object key = it.next();
242                o.object2Int.put(key, object2Int.get(key));
243            }
244            it = Int2Object.keySet().iterator();
245            while (it.hasNext()) {
246                Object key = it.next();
247                o.Int2Object.put(key, Int2Object.get(key));
248            }
249            return o;
250        }
251    }